package cn.ddiancan.auth.config;

import java.util.Objects;

import cn.ddiancan.xddcloud.common.context.SpringContextUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component
public class XddcloudBeanPostProcessor implements BeanPostProcessor {

    private static final String REALM_NAME = "Xddcloud";

    private static final String X_ACCESS_TOKEN = "x-access-token";

    private final BearerTokenAuthenticationEntryPoint authenticationEntryPoint = new BearerTokenAuthenticationEntryPoint();

    private OAuth2AuthorizationService oAuth2AuthorizationService;

    public OAuth2AuthorizationService getoAuth2AuthorizationService() {
        if (Objects.isNull(oAuth2AuthorizationService)) {
            oAuth2AuthorizationService = SpringContextUtils.getBean(OAuth2AuthorizationService.class);
        }
        return oAuth2AuthorizationService;

    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof BearerTokenAuthenticationFilter bearerTokenAuthenticationFilter) {
            bearerTokenAuthenticationFilter.setAuthenticationFailureHandler((request, response, exception) -> {
                String requestHeader = request.getHeader(X_ACCESS_TOKEN);
                if (StringUtils.hasText(requestHeader)) {
                    OAuth2Authorization byToken =
                        getoAuth2AuthorizationService().findByToken(requestHeader, OAuth2TokenType.ACCESS_TOKEN);
                    if (Objects.nonNull(byToken)) {
                        getoAuth2AuthorizationService().remove(byToken);
                    }
                }
                authenticationEntryPoint.setRealmName(REALM_NAME);
                authenticationEntryPoint.commence(request, response, exception);
            });
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}
